package com.chushouya.order.rabbitmq.sender;

import cn.hutool.json.JSONObject;
import com.chushouya.common.constant.PlatformTypeEnum;
import com.general.framework.core.lang.Jsons;
import com.chushouya.order.dto.api.partnernotify.NotifyQueue;
import com.chushouya.order.dto.mq.RabbitMessageDTO;
import com.chushouya.common.constant.RabbitMqQueueEnum;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 通知消息发送服务
 * 
 * @author chushouya
 * @date 2025-08-14
 */
@Slf4j
@Service
public class NotifyMessageSender {

    @Resource
    private RabbitTemplate rabbitTemplate;
    
    @Resource
    private ObjectMapper objectMapper;

    /**
     * 发送短信通知消息到队列
     * 
     * @param orderId 订单ID
     */
    public void sendSmsNotifyMessage(Long orderId) {
        try {
            RabbitMessageDTO message = createNotifyMessage(orderId, "SMS_NOTIFY");
            String queueName = RabbitMqQueueEnum.SMS_CLERK_NOTIFY.getQueueName();
            
            rabbitTemplate.convertAndSend(queueName, message);
            log.info("短信通知消息已发送到队列 - 队列: {}, 订单ID: {}, 消息ID: {}", 
                    queueName, orderId, message.getMessageId());
                    
        } catch (Exception e) {
            log.error("发送短信通知消息失败 - 订单ID: {}, 错误: {}", orderId, e.getMessage(), e);
            throw new RuntimeException("发送短信通知消息失败", e);
        }
    }

    /**
     * 发送微信通知消息到队列
     * 
     * @param orderId 订单ID
     */
    public void sendWechatNotifyMessage(Long orderId) {
        try {
            RabbitMessageDTO message = createNotifyMessage(orderId, "WECHAT_NOTIFY");
            String queueName = RabbitMqQueueEnum.WECHAT_CLERK_NOTIFY.getQueueName();
            
            rabbitTemplate.convertAndSend(queueName, message);
            log.info("微信通知消息已发送到队列 - 队列: {}, 订单ID: {}, 消息ID: {}", 
                    queueName, orderId, message.getMessageId());
                    
        } catch (Exception e) {
            log.error("发送微信通知消息失败 - 订单ID: {}, 错误: {}", orderId, e.getMessage(), e);
            throw new RuntimeException("发送微信通知消息失败", e);
        }
    }

    /**
     * 发送订单状态通知消息到队列
     * 
     * @param orderId 订单ID
     */
    public void sendOrderStatusNotifyMessage(Long orderId) {
        try {
            RabbitMessageDTO message = createNotifyMessage(orderId, "ORDER_STATUS_NOTIFY");
            String queueName = RabbitMqQueueEnum.ORDER_STATUS_USER_NOTIFY.getQueueName();
            
            rabbitTemplate.convertAndSend(queueName, message);
            log.info("订单状态通知消息已发送到队列 - 队列: {}, 订单ID: {}, 消息ID: {}", 
                    queueName, orderId, message.getMessageId());
                    
        } catch (Exception e) {
            log.error("发送订单状态通知消息失败 - 订单ID: {}, 错误: {}", orderId, e.getMessage(), e);
            throw new RuntimeException("发送订单状态通知消息失败", e);
        }
    }

    /**
     * 发送合作商订单状态通知消息到队列
     * 
     * @param orderId 订单ID
     * @param notifyType 通知类型
     * @param remark 备注
     */
    public void sendPartnerOrderStatusNotifyMessage(Long orderId, String notifyType, String remark) {
        try {
            RabbitMessageDTO message = createPartnerNotifyMessage(orderId, notifyType, remark);
            String queueName = RabbitMqQueueEnum.PARTNER_ORDER_STATUS_NOTIFY.getQueueName();
            
            rabbitTemplate.convertAndSend(queueName, message);
            log.info("合作商订单状态通知消息已发送到队列 - 队列: {}, 订单ID: {}, 通知类型: {}, 消息ID: {}", 
                    queueName, orderId, notifyType, message.getMessageId());
                    
        } catch (Exception e) {
            log.error("发送合作商订单状态通知消息失败 - 订单ID: {}, 通知类型: {}, 错误: {}", orderId, notifyType, e.getMessage(), e);
            throw new RuntimeException("发送合作商订单状态通知消息失败", e);
        }
    }

    /**
     * 发送支付宝订阅消息到队列
     * 
     * @param orderId 订单ID
     * @param platform 平台类型
     * @param messageType 消息类型（ORDER_SUCCESS, RECYCLE_CANCEL, PAYMENT_RECEIVED）
     */
    public void sendAlipaySubscribeMessage(Long orderId, String platform, String messageType) {
        if (!Objects.equal(platform, PlatformTypeEnum.ALIPAY.value())){
            log.info("非支付宝平台订单不发送订阅消息 - 订单ID: {}, 平台: {}", orderId, platform);
            return;
        }
        try {
            RabbitMessageDTO message = createAlipaySubscribeMessage(orderId, messageType);
            String queueName = RabbitMqQueueEnum.ALIPAY_SUBSCRIBE_MESSAGE.getQueueName();
            
            rabbitTemplate.convertAndSend(queueName, message);
            log.info("支付宝订阅消息已发送到队列 - 队列: {}, 订单ID: {}, 消息类型: {}, 消息ID: {}", 
                    queueName, orderId, messageType, message.getMessageId());
                    
        } catch (Exception e) {
            log.error("发送支付宝订阅消息失败 - 订单ID: {}, 消息类型: {}, 错误: {}", orderId, messageType, e.getMessage(), e);
            throw new RuntimeException("发送支付宝订阅消息失败", e);
        }
    }

    /**
     * 发送下单成功订阅消息
     * 
     * @param orderId 订单ID
     * @param platform 平台类型
     */
    public void sendOrderSuccessSubscribeMessage(Long orderId, String platform) {
        sendAlipaySubscribeMessage(orderId, platform, "ORDER_SUCCESS");
    }

    /**
     * 发送回收服务取消订阅消息
     * 
     * @param orderId 订单ID
     * @param platform 平台类型
     */
    public void sendRecycleCancelSubscribeMessage(Long orderId, String platform) {
        sendAlipaySubscribeMessage(orderId, platform, "RECYCLE_CANCEL");
    }

    /**
     * 发送回收金额已到账订阅消息
     * 
     * @param orderId 订单ID
     * @param platform 平台类型
     */
    public void sendPaymentReceivedSubscribeMessage(Long orderId, String platform) {
        sendAlipaySubscribeMessage(orderId, platform, "PAYMENT_RECEIVED");
    }
    

    /**
     * 创建通知消息
     * 
     * @param orderId 订单ID
     * @param messageType 消息类型
     * @return RabbitMessageDTO
     */
    private RabbitMessageDTO createNotifyMessage(Long orderId, String messageType) {
        RabbitMessageDTO message = new RabbitMessageDTO();
        message.setMessageId(UUID.randomUUID().toString());
        message.setMessageType(messageType);
        message.setData(String.valueOf(orderId));
        message.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        
        return message;
    }

    /**
     * 创建支付宝订阅消息
     * 
     * @param orderId 订单ID
     * @param subscribeType 订阅消息类型（ORDER_SUCCESS, RECYCLE_CANCEL, PAYMENT_RECEIVED）
     * @return RabbitMessageDTO
     */
    private RabbitMessageDTO createAlipaySubscribeMessage(Long orderId, String subscribeType) {
        RabbitMessageDTO message = new RabbitMessageDTO();
        message.setMessageId(UUID.randomUUID().toString());
        message.setMessageType("ALIPAY_SUBSCRIBE_MESSAGE");
        
        // 创建包含订单ID和订阅类型的消息数据
        JSONObject messageData = new JSONObject();
        messageData.put("orderId", orderId);
        messageData.put("subscribeType", subscribeType);
        
        message.setData(messageData.toString());
        message.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        
        return message;
    }

    /**
     * 创建合作商通知消息
     * 
     * @param orderId 订单ID
     * @param notifyType 通知类型
     * @param remark 备注
     * @return RabbitMessageDTO
     */
    private RabbitMessageDTO createPartnerNotifyMessage(Long orderId, String notifyType, String remark) {
        RabbitMessageDTO message = new RabbitMessageDTO();
        message.setMessageId(UUID.randomUUID().toString());
        message.setMessageType("PARTNER_ORDER_STATUS_NOTIFY");

        NotifyQueue notifyQueue = new NotifyQueue(orderId, notifyType, remark);
        message.setData(Jsons.toJsonString(notifyQueue));
        
        message.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        message.setRetryCount(0);
        message.setMaxRetryCount(3);
        
        return message;
    }

}
